//
// Created by wk on 2023/12/5.
//

#include <cstdlib>
#include <android/log.h>
#include "AudioEffect.h"


#define XLOGD(...) __android_log_print(ANDROID_LOG_DEBUG,"audioEffect",__VA_ARGS__)
#define XLOGI(...) __android_log_print(ANDROID_LOG_INFO,"audioEffect",__VA_ARGS__)
#define XLOGE(...) __android_log_print(ANDROID_LOG_ERROR,"audioEffect",__VA_ARGS__)


#define EQZ_IN_FACTOR (0.25f)


#define DB_TO_LINEAR(x) (pow(10.0, (x) / 20.0))
#define LINEAR_TO_DB(x) (20.0 * log10(x))

// Used to communicate the type of the filter.
enum kShelfType {
    kBass,
    kTreble
};

static void Coefficients(double hz, double slope, double gain, double samplerate, int type,
                         double &a0, double &a1, double &a2,
                         double &b0, double &b1, double &b2) {
    double w = 2 * M_PI * hz / samplerate;
    double a = exp(log(10.0) * gain / 40);
    double b = sqrt((a * a + 1) / slope - (pow((a - 1), 2)));

    if (type == kBass) {
        b0 = a * ((a + 1) - (a - 1) * cos(w) + b * sin(w));
        b1 = 2 * a * ((a - 1) - (a + 1) * cos(w));
        b2 = a * ((a + 1) - (a - 1) * cos(w) - b * sin(w));
        a0 = ((a + 1) + (a - 1) * cos(w) + b * sin(w));
        a1 = -2 * ((a - 1) + (a + 1) * cos(w));
        a2 = (a + 1) + (a - 1) * cos(w) - b * sin(w);
    } else //assumed kTreble
    {
        b0 = a * ((a + 1) + (a - 1) * cos(w) + b * sin(w));
        b1 = -2 * a * ((a - 1) + (a + 1) * cos(w));
        b2 = a * ((a + 1) + (a - 1) * cos(w) - b * sin(w));
        a0 = ((a + 1) - (a - 1) * cos(w) + b * sin(w));
        a1 = 2 * ((a - 1) - (a + 1) * cos(w));
        a2 = (a + 1) - (a - 1) * cos(w) - b * sin(w);
    }
}

float audio_effect::BassEffect::doFilter(BassEffect &data, float in) {
    // Bass filter
    float out = (data.b0Bass * in + data.b1Bass * data.xn1Bass + data.b2Bass * data.xn2Bass -
                 data.a1Bass * data.yn1Bass - data.a2Bass * data.yn2Bass) / data.a0Bass;
    data.xn2Bass = data.xn1Bass;
    data.xn1Bass = in;
    data.yn2Bass = data.yn1Bass;
    data.yn1Bass = out;
    return out;
}

void audio_effect::BassEffect::process(float *inBlock, float *outBlock, size_t block_len) {

    double oldBass = DB_TO_LINEAR(mBass);
    if (true) {
        Coefficients(this->hzBass, this->slope, this->mBass, this->samplerate, kBass, this->a0Bass,
                     this->a1Bass, this->a2Bass, this->b0Bass, this->b1Bass, this->b2Bass);
        update = false;
    }

    for (int i = 0; i < block_len; i++) {
        outBlock[i] = doFilter(*this, inBlock[i]);
    }

}

audio_effect::BassEffect::BassEffect(float samplerate) {

    this->samplerate = samplerate;
    this->slope = 0.4f;   // same slope for both filters
    this->hzBass = 250.0f;   // could be tunable in a more advanced version
    this->a0Bass = 1;
    this->a1Bass = 0;
    this->a2Bass = 0;
    this->b0Bass = 0;
    this->b1Bass = 0;
    this->b2Bass = 0;

    this->xn1Bass = 0;
    this->xn2Bass = 0;
    this->yn1Bass = 0;
    this->yn2Bass = 0;

    this->bass = -1;
    this->gain = DB_TO_LINEAR(mGain);
}

void audio_effect::BassEffect::setBass(float db) {
    this->mBass = db;
    update = true;
}


#define SQR(x) ((x) * (x))

static double vb_fun(double x) {
    double y = 2.5 * atan(0.9 * x) + 2.5 * sqrt(1. - SQR(0.9 * x)) - 2.5;

    return y < 0. ? sin(y) : y;
}

void audio_effect::VirtualBass::init() {
    const double Q = 0.707;
    double g, k;

    g = tan(M_PI * this->cutoff / this->sample_rate);
    k = 1. / Q;
    this->a[0] = 1. / (1. + g * (g + k));
    this->a[1] = g * this->a[0];
    this->a[2] = g * this->a[1];
    this->m[0] = 0.;
    this->m[1] = 0.;
    this->m[2] = 1.;
}


double audio_effect::VirtualBass::process(double x) {

    const double st = M_PI / this->strength;
    const double a0 = this->a[0];
    const double a1 = this->a[1];
    const double a2 = this->a[2];
    const double m0 = this->m[0];
    const double m1 = this->m[1];
    const double m2 = this->m[2];
    double b0 = this->cf[0];
    double b1 = this->cf[1];

    const double v0 = x;
    const double v3 = v0 - b1;
    const double v1 = a0 * b0 + a1 * v3;
    const double v2 = b1 + a1 * b0 + a2 * v3;
    double b, vb;

    b0 = 2. * v1 - b0;
    b1 = 2. * v2 - b1;

    b = m0 * v0 + m1 * v1 + m2 * v2;
    vb = sin(vb_fun(b) * st);

    this->cf[0] = b0;
    this->cf[1] = b1;

    return vb;
}

void audio_effect::VirtualBass::process(float *inBlock, float *outBlock, size_t block_len) {
    for (int i = 0; i < block_len; i++) {
        outBlock[i] = process((double) inBlock[i]);
    }
}

audio_effect::VirtualBass::VirtualBass() {
    init();
}


#define NB_PRESETS 18

#define EQZ_BANDS_MAX 10

/* The frequency tables */
static const float f_vlc_frequency_table_10b[EQZ_BANDS_MAX] =
        {
                60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000,
        };

static const float f_iso_frequency_table_10b[EQZ_BANDS_MAX] =
        {
                31.25, 62.5, 125, 250, 500, 1000, 2000, 4000, 8000, 16000,
        };


typedef struct {
    const char psz_name[16];
    int i_band;
    float f_preamp;
    float f_amp[EQZ_BANDS_MAX];
} eqz_preset_t;


static const eqz_preset_t eqz_preset_10b[NB_PRESETS] =
        {
                {
                        "flat",           10, 12.0f,
                        {0.0f,          0.0f,          0.0f,          0.0f,          0.0f,          0.0f,          0.0f,          0.0f,          0.0f,          0.0f},
                },
                {
                        "classical",      10, 12.0f,
                        {-1.11022e-15f, -1.11022e-15f, -1.11022e-15f, -1.11022e-15f,
                                                                                     -1.11022e-15f, -1.11022e-15f, -7.2f,         -7.2f,         -7.2f,         -9.6f}
                },
                {
                        "club",           10, 6.0f,
                        {-1.11022e-15f, -1.11022e-15f, 8.0f,          5.6f,          5.6f,          5.6f,          3.2f,
                                                                                                                                  -1.11022e-15f, -1.11022e-15f, -1.11022e-15f}
                },
                {
                        "dance",          10, 5.0f,
                        {9.6f,          7.2f,          2.4f,          -1.11022e-15f, -1.11022e-15f, -5.6f,         -7.2f,         -7.2f,
                                                                                                                                                 -1.11022e-15f, -1.11022e-15f}
                },
                {
                        "fullbass",       10, 5.0f,
                        {-8.0f,         9.6f,          9.6f,          5.6f,          1.6f,          -4.0f,         -8.0f,         -10.4f,        -11.2f,        -11.2f}
                },
                {
                        "fullbasstreble", 10, 4.0f,
                        {7.2f,          5.6f,          -1.11022e-15f, -7.2f,         -4.8f,         1.6f,          8.0f,          11.2f,
                                                                                                                                                 12.0f,         12.0f}
                },
                {
                        "fulltreble",     10, 3.0f,
                        {-9.6f,         -9.6f,         -9.6f,         -4.0f,         2.4f,          11.2f,         16.0f,         16.0f,         16.0f,         16.8f}
                },
                {
                        "headphones",     10, 4.0f,
                        {4.8f,          11.2f,         5.6f,          -3.2f,         -2.4f,         1.6f,          4.8f,          9.6f,          12.8f,         14.4f}
                },
                {
                        "largehall",      10, 5.0f,
                        {10.4f,         10.4f,         5.6f,          5.6f,          -1.11022e-15f, -4.8f,         -4.8f,         -4.8f,
                                                                                                                                                 -1.11022e-15f, -1.11022e-15f}
                },
                {
                        "live",           10, 7.0f,
                        {-4.8f,         -1.11022e-15f, 4.0f,          5.6f,          5.6f,          5.6f,          4.0f,          2.4f,
                                                                                                                                                 2.4f,          2.4f}
                },
                {
                        "party",          10, 6.0f,
                        {7.2f,          7.2f,          -1.11022e-15f, -1.11022e-15f, -1.11022e-15f,
                                                                                                    -1.11022e-15f, -1.11022e-15f, -1.11022e-15f, 7.2f,          7.2f}
                },
                {
                        "pop",            10, 6.0f,
                        {-1.6f,         4.8f,          7.2f,          8.0f,          5.6f,          -1.11022e-15f, -2.4f,         -2.4f,
                                                                                                                                                 -1.6f,         -1.6f}
                },
                {
                        "reggae",         10, 8.0f,
                        {-1.11022e-15f, -1.11022e-15f, -1.11022e-15f, -5.6f,         -1.11022e-15f,
                                                                                                    6.4f,          6.4f,          -1.11022e-15f, -1.11022e-15f, -1.11022e-15f}
                },
                {
                        "rock",           10, 5.0f,
                        {8.0f,          4.8f,          -5.6f,         -8.0f,         -3.2f,         4.0f,          8.8f,          11.2f,         11.2f,         11.2f}
                },
                {
                        "ska",            10, 6.0f,
                        {-2.4f,         -4.8f,         -4.0f,         -1.11022e-15f, 4.0f,          5.6f,          8.8f,          9.6f,
                                                                                                                                                 11.2f,         9.6f}
                },
                {
                        "soft",           10, 5.0f,
                        {4.8f,          1.6f,          -1.11022e-15f, -2.4f,         -1.11022e-15f, 4.0f,          8.0f,          9.6f,
                                                                                                                                                 11.2f,         12.0f}
                },
                {
                        "softrock",       10, 7.0f,
                        {4.0f,          4.0f,          2.4f,          -1.11022e-15f, -4.0f,         -5.6f,         -3.2f,         -1.11022e-15f,
                                                                                                                                                 2.4f,          8.8f}
                },
                {
                        "techno",         10, 5.0f,
                        {8.0f,          5.6f,          -1.11022e-15f, -5.6f,         -4.8f,         -1.11022e-15f, 8.0f,          9.6f,
                                                                                                                                                 9.6f,          8.8f}
                },
        };


/*****************************************************************************
 * Equalizer stuff
 *****************************************************************************/
typedef struct {
    int i_band;

    struct {
        float f_frequency;
        float f_alpha;
        float f_beta;
        float f_gamma;
    } band[EQZ_BANDS_MAX];

} eqz_config_t;


/* Equalizer coefficient calculation function based on equ-xmms */
static void EqzCoeffs(int i_rate, float f_octave_percent,
                      bool b_use_vlc_freqs,
                      eqz_config_t *p_eqz_config) {
    const float *f_freq_table_10b = b_use_vlc_freqs
                                    ? f_vlc_frequency_table_10b
                                    : f_iso_frequency_table_10b;
    float f_rate = (float) i_rate;
    float f_nyquist_freq = 0.5f * f_rate;
    float f_octave_factor = powf(2.0f, 0.5f * f_octave_percent);
    float f_octave_factor_1 = 0.5f * (f_octave_factor + 1.0f);
    float f_octave_factor_2 = 0.5f * (f_octave_factor - 1.0f);

    p_eqz_config->i_band = EQZ_BANDS_MAX;

    for (int i = 0; i < EQZ_BANDS_MAX; i++) {
        float f_freq = f_freq_table_10b[i];

        p_eqz_config->band[i].f_frequency = f_freq;

        if (f_freq <= f_nyquist_freq) {
            float f_theta_1 = (2.0f * (float) M_PI * f_freq) / f_rate;
            float f_theta_2 = f_theta_1 / f_octave_factor;
            float f_sin = sinf(f_theta_2);
            float f_sin_prd = sinf(f_theta_2 * f_octave_factor_1)
                              * sinf(f_theta_2 * f_octave_factor_2);
            float f_sin_hlf = f_sin * 0.5f;
            float f_den = f_sin_hlf + f_sin_prd;

            p_eqz_config->band[i].f_alpha = f_sin_prd / f_den;
            p_eqz_config->band[i].f_beta = (f_sin_hlf - f_sin_prd) / f_den;
            p_eqz_config->band[i].f_gamma = f_sin * cosf(f_theta_1) / f_den;
        } else {
            /* Any frequency beyond the Nyquist frequency is no good... */
            p_eqz_config->band[i].f_alpha =
            p_eqz_config->band[i].f_beta =
            p_eqz_config->band[i].f_gamma = 0.0f;
        }
    }
}

static inline float EqzConvertdB(float db) {
    /* Map it to gain,
     * (we do as if the input of iir is /EQZ_IN_FACTOR, but in fact it's the non iir data that is *EQZ_IN_FACTOR)
     * db = 20*log( out / in ) with out = in + amp*iir(i/EQZ_IN_FACTOR)
     * or iir(i) == i for the center freq so
     * db = 20*log( 1 + amp/EQZ_IN_FACTOR )
     * -> amp = EQZ_IN_FACTOR*(10^(db/20) - 1)
     **/

    if (db < -20.0f)
        db = -20.0f;
    else if (db > 20.0f)
        db = 20.0f;
    return EQZ_IN_FACTOR * (powf(10.0f, db / 20.0f) - 1.0f);
}

/**
 *
 */
audio_effect::EqualizerEffect::EqualizerEffect(int i_rate) {
    init(i_rate);
}

void audio_effect::EqualizerEffect::init(int i_rate) {

    bool b_vlcFreqs = true;
    eqz_config_t cfg;
    EqzCoeffs(i_rate, 1.0f, b_vlcFreqs, &cfg);

    this->i_band = cfg.i_band;
    this->f_alpha = new float[this->i_band];
    this->f_beta = new float[this->i_band];
    this->f_gamma = new float[this->i_band];

    for (int i = 0; i < this->i_band; i++) {
        this->f_alpha[i] = cfg.band[i].f_alpha;
        this->f_beta[i] = cfg.band[i].f_beta;
        this->f_gamma[i] = cfg.band[i].f_gamma;
    }

    this->b_2eqz = false;

    this->f_gamp = 1.0f;
    this->f_amp = new float[this->i_band];
    for (int i = 0; i < this->i_band; i++) {
        this->f_amp[i] = 0.0f;
    }

    /* Filter state */
    for (int ch = 0; ch < 1; ch++) {
        this->x[ch][0] =
        this->x[ch][1] =
        this->x2[ch][0] =
        this->x2[ch][1] = 0.0f;

        for (int i = 0; i < this->i_band; i++) {
            this->y[ch][i][0] =
            this->y[ch][i][1] =
            this->y2[ch][i][0] =
            this->y2[ch][i][1] = 0.0f;
        }
    }


}


audio_effect::EqualizerEffect::~EqualizerEffect() {
    if (this->f_alpha) {
        delete[]this->f_alpha;
    }

    if (this->f_beta) {
        delete[]this->f_beta;
    }
    if (this->f_gamma) {
        delete[]this->f_gamma;
    }

}


void audio_effect::EqualizerEffect::process(float *inBlock, float *outBlock, size_t block_len) {
    std::lock_guard<std::mutex> lock(mLock);
    int i, ch = 0, j;


    for (int i = 0; i < block_len; i++) {
        const float x = inBlock[i];
        float o = 0.0f;

        for (j = 0; j < this->i_band; j++) {
            float y = this->f_alpha[j] * (x - this->x[ch][1]) +
                      this->f_gamma[j] * this->y[ch][j][0] -
                      this->f_beta[j] * this->y[ch][j][1];

            this->y[ch][j][1] = this->y[ch][j][0];
            this->y[ch][j][0] = y;

            o += y * this->f_amp[j];
        }
        this->x[ch][1] = this->x[ch][0];
        this->x[ch][0] = x;

        /* Second filter */
        if (this->b_2eqz) {
            const float x2 = EQZ_IN_FACTOR * x + o;
            o = 0.0f;
            for (j = 0; j < this->i_band; j++) {
                float y = this->f_alpha[j] * (x2 - this->x2[ch][1]) +
                          this->f_gamma[j] * this->y2[ch][j][0] -
                          this->f_beta[j] * this->y2[ch][j][1];

                this->y2[ch][j][1] = this->y2[ch][j][0];
                this->y2[ch][j][0] = y;

                o += y * this->f_amp[j];
            }
            this->x2[ch][1] = this->x2[ch][0];
            this->x2[ch][0] = x2;

            /* We add source PCM + filtered PCM */
            outBlock[i] = this->f_gamp * this->f_gamp * (EQZ_IN_FACTOR * x2 + o);
        } else {
            /* We add source PCM + filtered PCM */
            outBlock[i] = this->f_gamp * (EQZ_IN_FACTOR * x + o);
        }
    }


}

void audio_effect::EqualizerEffect::update(int bandIndex, float db) {
    //this->f_amp[bandIndex] = EqzConvertdB(db);

    static int s_preset_index = 0;
    for (int i = 0; i < 10; i++) {
        if (isnan(eqz_preset_10b[s_preset_index].f_amp[i])) {
            this->f_amp[i] = EqzConvertdB(.0f);
        } else {
            this->f_amp[i] = EqzConvertdB(eqz_preset_10b[s_preset_index].f_amp[i]);
        }


        XLOGI("---------- f_amp:%f", this->f_amp[i]);
    }

    this->f_gamp = eqz_preset_10b[s_preset_index].f_preamp;


    XLOGI("-----------preset :%d", s_preset_index);
    s_preset_index++;
    s_preset_index = s_preset_index % 18;

}

void audio_effect::EqualizerEffect::updatePreset(const char *psz_preset) {
    const eqz_preset_t *preset = NULL;

    for (unsigned i = 0; i < NB_PRESETS; i++)
        if (!strcasecmp(eqz_preset_10b[i].psz_name, psz_preset)) {
            preset = eqz_preset_10b + i;
            break;
        }

    if (preset == NULL) {
        XLOGE("----------- preset null");
        return;
    }

    for (int i = 0; i < 10; i++) {
        if (isnan(preset->f_amp[i])) {
            this->f_amp[i] = EqzConvertdB(.0f);
        } else {
            this->f_amp[i] = EqzConvertdB(preset->f_amp[i]);
        }


        XLOGI("---------- f_amp:%f", this->f_amp[i]);
    }

    updateAmp(preset->f_preamp);

//    this->f_gamp = 1.0f;

}

void audio_effect::EqualizerEffect::updateAmp(float db) {


    if (db < -20.f)
        this->f_gamp = .1f;
    else if (db < 20.f)
        this->f_gamp = powf(10.f, db / 20.f);
    else
        this->f_gamp = 10.f;

    XLOGI("--------preset amp :%f", this->f_gamp);
}


audio_effect::BiQuad::BiQuad(audio_effect::BiQuad::Type type, double dbGain, double freq,
                             double srate, double bandwidthOrQOrS, bool isBandwidthOrS) {
    double A;
    if (type == PEAKING || type == LOW_SHELF || type == HIGH_SHELF)
        A = pow(10, dbGain / 40);
    else
        A = pow(10, dbGain / 20);
    double omega = 2 * M_PI * freq / srate;
    double sn = sin(omega);
    double cs = cos(omega);
    double alpha;

    if (!isBandwidthOrS) // Q
        alpha = sn / (2 * bandwidthOrQOrS);
    else if (type == LOW_SHELF || type == HIGH_SHELF) // S
        alpha = sn / 2 * sqrt((A + 1 / A) * (1 / bandwidthOrQOrS - 1) + 2);
    else // BW
        alpha = sn * sinh(M_LN2 / 2 * bandwidthOrQOrS * omega / sn);

    double beta = 2 * sqrt(A) * alpha;

    double b0, b1, b2, a0, a1, a2;

    switch (type) {
        case LOW_PASS:
            b0 = (1 - cs) / 2;
            b1 = 1 - cs;
            b2 = (1 - cs) / 2;
            a0 = 1 + alpha;
            a1 = -2 * cs;
            a2 = 1 - alpha;
            break;
        case HIGH_PASS:
            b0 = (1 + cs) / 2;
            b1 = -(1 + cs);
            b2 = (1 + cs) / 2;
            a0 = 1 + alpha;
            a1 = -2 * cs;
            a2 = 1 - alpha;
            break;
        case BAND_PASS:
            b0 = alpha;
            b1 = 0;
            b2 = -alpha;
            a0 = 1 + alpha;
            a1 = -2 * cs;
            a2 = 1 - alpha;
            break;
        case NOTCH:
            b0 = 1;
            b1 = -2 * cs;
            b2 = 1;
            a0 = 1 + alpha;
            a1 = -2 * cs;
            a2 = 1 - alpha;
            break;
        case ALL_PASS:
            b0 = 1 - alpha;
            b1 = -2 * cs;
            b2 = 1 + alpha;
            a0 = 1 + alpha;
            a1 = -2 * cs;
            a2 = 1 - alpha;
            break;
        case PEAKING:
            b0 = 1 + (alpha * A);
            b1 = -2 * cs;
            b2 = 1 - (alpha * A);
            a0 = 1 + (alpha / A);
            a1 = -2 * cs;
            a2 = 1 - (alpha / A);
            break;
        case LOW_SHELF:
            b0 = A * ((A + 1) - (A - 1) * cs + beta);
            b1 = 2 * A * ((A - 1) - (A + 1) * cs);
            b2 = A * ((A + 1) - (A - 1) * cs - beta);
            a0 = (A + 1) + (A - 1) * cs + beta;
            a1 = -2 * ((A - 1) + (A + 1) * cs);
            a2 = (A + 1) + (A - 1) * cs - beta;
            break;
        case HIGH_SHELF:
            b0 = A * ((A + 1) + (A - 1) * cs + beta);
            b1 = -2 * A * ((A - 1) + (A + 1) * cs);
            b2 = A * ((A + 1) + (A - 1) * cs - beta);
            a0 = (A + 1) - (A - 1) * cs + beta;
            a1 = 2 * ((A - 1) - (A + 1) * cs);
            a2 = (A + 1) - (A - 1) * cs - beta;
            break;
    }

    this->a0 = b0 / a0;
    this->a[0] = b1 / a0;
    this->a[1] = b2 / a0;
    this->a[2] = a1 / a0;
    this->a[3] = a2 / a0;

    x1 = 0;
    x2 = 0;
    y1 = 0;
    y2 = 0;
}

void audio_effect::BiQuad::removeDenormals() {
    if (IS_DENORMAL(x1))
        x1 = 0.0;
    if (IS_DENORMAL(x2))
        x2 = 0.0;
    if (IS_DENORMAL(y1))
        y1 = 0.0;
    if (IS_DENORMAL(y2))
        y2 = 0.0;
}

double audio_effect::BiQuad::process(double sample) {
    // changed order of additions leads to better pipelining
    double result = a0 * sample + a[1] * x2 + a[0] * x1 - a[3] * y2 - a[2] * y1;

    x2 = x1;
    x1 = sample;

    y2 = y1;
    y1 = result;

    return result;
}

void audio_effect::BiQuad::setCoefficients(double *ain, const double &a0in) {
    for (int i = 0; i < 4; i++)
        a[i] = ain[i];
    a0 = a0in;
}

#define EQZ_BAND_VALUE_SIZE 12

/**
 * Internal equalizer structure.
 */
struct libvlc_equalizer_t {
    float f_preamp;
    float f_amp[EQZ_BANDS_MAX];
};

void audio_effect::test() {


    for (int i = 0; i < 10; i++) {
        eqz_preset_t *preset = (eqz_preset_t *) &eqz_preset_10b[1];
        char *bands = NULL;

        for (unsigned i = 0; i < EQZ_BANDS_MAX; i++) {
            char *psz;

            lldiv_t d = lldiv(lroundf(preset->f_amp[i] * 10000000.f), 10000000);

            if (asprintf(&psz, "%s %lld.%07llu", i ? bands : "",
                         d.quot, d.rem) == -1)
                psz = NULL;

            free(bands);
            bands = psz;
        }

        XLOGI("index:%d  bands:%s", i, bands);
    }


    libvlc_equalizer_t *p_equalizer = new libvlc_equalizer_t();

    for (int i = 0; i < 10; i++) {
        p_equalizer->f_amp[i] = eqz_preset_10b[6].f_amp[i];
    }

    //bands
    char bands[EQZ_BANDS_MAX * EQZ_BAND_VALUE_SIZE + 1];

    if (p_equalizer != NULL) {
        for (unsigned i = 0, c = 0; i < EQZ_BANDS_MAX; i++) {
            c += snprintf(bands + c, sizeof(bands) - c, " %.07f",
                          p_equalizer->f_amp[i]);
//            if( unlikely(c >= sizeof(bands)) )
//                return ;
        }

        XLOGI("bands %s\n", bands);
//        var_SetFloat( p_mi, "equalizer-preamp", p_equalizer->f_preamp );
//        var_SetString( p_mi, "equalizer-bands", bands );
    }


    //callback bands
    {
        const char *p = bands;
        int i = 0;
        int i_band = 10;

        float f_amp[10] = {0};

        /* Same thing for bands */
        while (i < 10) {
            char *next;
            /* Read dB -20/20 */
            float f = strtof(p, &next);
            if (next == p || isnan(f))
                break; /* no conversion */

            f_amp[i++] = EqzConvertdB(f);

            if (*next == '\0')
                break; /* end of line */
            p = &next[1];
        }
        while (i < i_band)
            f_amp[i++] = EqzConvertdB(0.f);


        for (int i = 0; i < i_band; i++) {
            XLOGI("f_amp %f \n", f_amp[i]);
        }
    }
}
